package com.gjs.common.aop.tracing;

import brave.Tracer;
import cn.hutool.extra.servlet.ServletUtil;
import com.gjs.common.manager.response.RspBody;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;

@Slf4j
@Aspect
@Component
public class TraceAspect {

    @Autowired
    private Tracer tracer;

    // 定义切点Pointcut
    @Pointcut("execution(* com.gjs.*.controller..*.*(..))")
    public void pointcut() {
    }

    @Around("pointcut()")
    public Object doAround(ProceedingJoinPoint pjp) throws Throwable {
        RequestAttributes ra = RequestContextHolder.getRequestAttributes();
        ServletRequestAttributes sra = (ServletRequestAttributes) ra;
        HttpServletRequest request = sra.getRequest();
        // 获取请求信息
        String url = request.getRequestURL().toString();
        String method = request.getMethod();
        String queryString = request.getQueryString();
        String clientIp = ServletUtil.getClientIP(request);
        // 获取sleuth中的traceId
        String traceId = tracer.currentSpan().context().traceIdString();

        log.info("请求开始, traceId:{}, 客户端IP: {} 入参, url: {}, method: {}, params: {}", traceId, clientIp, url, method, queryString);

        Object result = pjp.proceed();
        // 拦截返回的RspBody，并设置RspBody中的traceId
        RspBody rspBody = null;
        if(result instanceof RspBody){
            rspBody = (RspBody) result;
            rspBody.setTraceId(traceId);
        }

        log.info("请求结束, traceId:{}", traceId);

        return rspBody != null ? rspBody : result;
    }
}
